package com.lin.netty.module.byteBuf;

import com.lin.netty.utils.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.junit.Test;

/**
 * ByteBuf
 * 0、优势
 * 对之前NIO中ByteBuffer的改进，ByteBuffer读写共用一个指针，读写还要调用flip clear方法切换，很麻烦，
 * ByteBuf读写指针分开，读写更方便，然后还能自动扩容。
 * 池化 - 可以重用池中 ByteBuf 实例，更节约内存，减少内存溢出的可能
 * 支持链式调用，使用更流畅
 * 很多地方体现零拷贝，例如 slice、duplicate、CompositeByteBuf
 *
 * 1、创建
 * ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); 默认容量是256个字节，当写入的字节超过了会自动扩容
 *
 * 2、基于直接内存和堆内存的ByteBuf
 * 直接内存创建和销毁的代价昂贵，但读写性能高（少一次内存复制），适合配合池化功能一起用
 * 堆内存读写性能较低，因
 *
 * 3、是否使用池化
 * 池化的最大意义在于可以重用 ByteBuf，优点有：
 * 没有池化，则每次都得创建新的 ByteBuf 实例，这个操作对直接内存代价昂贵，就算是堆内存，也会增加 GC 压力
 * 有了池化，则可以重用池中 ByteBuf 实例，并且采用了与 jemalloc 类似的内存分配算法提升分配效率
 * 高并发时，池化功能更节约内存，减少内存溢出的可能
 *
 * 池化功能是否开启，可以通过下面的系统环境变量来设置 ： -Dio.netty.allocator.type={unpooled|pooled}
 *
 * 4、方法
 * 主要有写入和读取
 * byte short int long flot double boolean char （12484812）
 *
 * 5、内存释放
 * ByteBuf用完后如何进行内存释放？
 * 由于 Netty 中有堆外内存的 ByteBuf 实现，堆外内存最好是手动来释放，而不是等 GC 垃圾回收
 *      UnpooledHeapByteBuf 使用的是 JVM 内存，只需等 GC 回收内存即可
 *      UnpooledDirectByteBuf 使用的就是直接内存了，需要特殊的方法来回收内存
 *      PooledByteBuf 和它的子类使用了池化机制，需要更复杂的规则来回收内存
 *
 * Netty 采用了引用计数法来控制回收内存，每个 ByteBuf 实现类 都实现了 ReferenceCounted 接口
 * * 每个 ByteBuf 对象的初始计数为 1
 * * 调用 release 方法计数减 1，如果计数为 0，ByteBuf 内存被回收
 * * 调用 retain 方法计数加 1，表示调用者没用完之前，其它 handler 即使调用了 release 也不会造成回收
 * * 当计数为 0 时，底层内存会被回收，这时即使 ByteBuf 对象还在，其各个方法均无法正常使用
 *
 * 应该由最后一个ByteBuf的使用者调用release，当然入站消息传到最后一个handler tail 还是ByteBuf类型的话，会自动帮我们释放。
 * 如果出站消息是ByteBuf类型的，也会帮我们释放消息所占的内存
 */
public class ByteBufTest {
    public static void main(String[] args) {
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();

        System.out.println(byteBuf.getClass());
        System.out.println(byteBuf);
        for (int i = 0; i < 300; i++) {
            byteBuf.writeByte(97);
        }
        System.out.println(byteBuf);
    }

    /**
     * 	                            大端字节序（Big-Endian）	                            小端字节序（Little-Endian）
     * 特点	                        高位字节在低地址	                                    低位字节在低地址
     * 示例（32位整数0x12345678）	    0x12 0x34 0x56 0x78	                             0x78 0x56 0x34 0x12
     * 应用场景	大型机器、网络设备、网络通信（网络字节序）、某些处理器架构（如MIPS、PowerPC）	个人计算机、服务器（x86、x86-64架构）、大多数Linux系统、Windows系统、macOS、大多数UNIX系统、某些ARM处理器
     */
    @Test
    public void testByteOrder(){
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
//        byteBuf.writeInt(129); // 00 00 00 81
        byteBuf.writeIntLE(129); // 81 00 00 00
        byte[] dst = new byte[5];
        byteBuf.getBytes(0, dst);
        ByteBufUtils.log(byteBuf);
    }
}
